package com.open4cn.simulator.device.huagao;

import com.open4cn.simulator.connect.tcp.TCPClientConnector;
import com.open4cn.simulator.connect.tcp.handler.DispatcherHandler;
import com.open4cn.simulator.connect.tcp.handler.ReadBlockHandler;
import com.open4cn.simulator.connect.tcp.handler.ReadLogHandler;
import com.open4cn.simulator.connect.tcp.handler.ReconnectHandler;
import com.open4cn.simulator.connect.tcp.handler.WriteLogHandler;
import com.open4cn.simulator.connect.tcp.listenner.ConnectStatusFutureListener;
import com.open4cn.simulator.core.connector.ConnectAddress;
import com.open4cn.simulator.core.connector.IConnector;
import com.open4cn.simulator.core.device.DeviceInfo;
import com.open4cn.simulator.core.device.DeviceParameters;
import com.open4cn.simulator.core.device.DeviceStatus;
import com.open4cn.simulator.core.device.IDevice;
import com.open4cn.simulator.core.device.IDeviceFactory;
import com.open4cn.simulator.core.ext.HuaGaoParameters;
import com.open4cn.simulator.core.ext.HuaGaoStatus;
import com.open4cn.simulator.core.parser.IInstructionParser;
import com.open4cn.simulator.core.parser.InstructionParserChain;
import com.open4cn.simulator.device.AnswerManager;
import com.open4cn.simulator.device.DeviceStatusManager;
import com.open4cn.simulator.parser.huagao.HGUnknown;
import com.open4cn.simulator.parser.huagao.hg9000.DL;
import com.open4cn.simulator.parser.huagao.hg9000.MD;
import com.open4cn.simulator.parser.huagao.hg9000.QA;
import com.open4cn.simulator.parser.huagao.hg9000.QM;
import com.open4cn.simulator.parser.huagao.hg9000.RN;
import com.open4cn.simulator.parser.huagao.hg9000.RS;
import com.open4cn.simulator.parser.huagao.hg9000.ST;
import com.open4cn.simulator.parser.huagao.hg9000.UL;
import com.open4cn.simulator.parser.huagao.hg9000.UP;
import com.open4cn.simulator.protocol.huagao.HuaGaoDecoder;
import com.open4cn.simulator.protocol.huagao.HuaGaoEncoder;

import java.util.Arrays;
import java.util.List;

/**
 * @author yinxiaopeng
 * @version 1.0.0
 * @company 致景科技
 * @department 飞梭BU/研发
 * @description
 * @Email yinxiaopeng@zj.tech
 * @date 2022-05-06 12:19
 */
public class HuaGao9000Factory implements IDeviceFactory {


    @Override
    public IDevice build(DeviceParameters parameters) {
        HuaGao9000 huaGao9000 = new HuaGao9000();
        huaGao9000.setDeviceInfo(deviceInfo(parameters));
        huaGao9000.setConnector(connector(huaGao9000.getDeviceInfo()));
        return huaGao9000;
    }


    private DeviceInfo<HuaGaoParameters, HuaGaoStatus> deviceInfo(DeviceParameters parameters) {
        DeviceInfo<HuaGaoParameters, HuaGaoStatus> deviceInfo = new DeviceInfo<>();
        deviceInfo.setId(parameters.getId());
        deviceInfo.setName(parameters.getName());
        deviceInfo.setBrand(parameters.getBrand());
        deviceInfo.setModel(parameters.getModel());
        deviceInfo.setDeviceStatus(deviceStatus(deviceInfo));
        deviceInfo.setConnectAddress(new ConnectAddress(parameters.getString(HGPredefinedAttributes.HOST), parameters.getInteger(HGPredefinedAttributes.PORT)));

        // 华高设备参数
        HuaGaoParameters huaGaoParameters = new HuaGaoParameters();
        huaGaoParameters.setStationNo(parameters.getString(HGPredefinedAttributes.STATION_NO));
        deviceInfo.setParameters(huaGaoParameters);
        return deviceInfo;
    }


    private DeviceStatus deviceStatus(DeviceInfo deviceInfo) {
        String deviceId = deviceInfo.getId();
        DeviceStatusManager deviceStatusManager = DeviceStatusManager.getInstance();
        DeviceStatus deviceStatus = deviceStatusManager.load(deviceId);
        if (null == deviceStatus) {
            deviceStatus = new DeviceStatus(deviceId, deviceInfo.getBrand(), deviceInfo.getModel(), new HuaGaoStatus());
        }
        deviceStatusManager.put(deviceId, deviceStatus);
        return deviceStatus;
    }

    private IConnector connector(DeviceInfo deviceInfo) {
        HuaGaoParameters huaGaoParameters = (HuaGaoParameters) deviceInfo.getParameters();
        TCPClientConnector connector = new TCPClientConnector();
        connector.beforeDecod(new ReconnectHandler(connector, deviceInfo.getConnectAddress()));
        // connector.beforeDecod(new HuaGaoHeartbeatHandler(deviceInfo.getDeviceStatus(),huaGaoParameters.getStationNo()));
        // connector.beforeDecod(new HuaGaoStateReportHandler(deviceInfo.getDeviceStatus(),huaGaoParameters.getStationNo()));
        connector.beforeDecod(new ReadLogHandler(deviceInfo.getName()));
        connector.beforeDecod(new ReadBlockHandler(deviceInfo.getDeviceStatus()));
        connector.decoder(HuaGaoDecoder.class);
        connector.afterDecod(new DispatcherHandler(chain(deviceInfo)));
        connector.encoder(HuaGaoEncoder.class);
        connector.afterEncod(new WriteLogHandler(deviceInfo.getName()));
        connector.addFutureListenner(new ConnectStatusFutureListener(connector.getConnectStatus()));
        return connector;
    }

    private InstructionParserChain chain(DeviceInfo deviceInfo) {
        HuaGaoStatus huaGaoStatus = (HuaGaoStatus) deviceInfo.getDeviceStatus().getData();
        List<IInstructionParser> parsers = Arrays.asList(
                new RN(huaGaoStatus),
                new UP(huaGaoStatus),
                new UL(huaGaoStatus),
                new MD(huaGaoStatus),
                new DL(huaGaoStatus),
                new QA(huaGaoStatus),
                new QM(huaGaoStatus),
                new ST(huaGaoStatus),
                new RS(huaGaoStatus),
                new HGUnknown()
        );
        manageAnswer(deviceInfo.getId(), parsers);
        return new InstructionParserChain(parsers);
    }

    private void manageAnswer(String deviceId, List<IInstructionParser> parsers) {
        AnswerManager answerManager = AnswerManager.getInstance();
        parsers.forEach(parser -> {
            answerManager.put(deviceId, parser.getAnswers());
        });
    }
}
